﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CS_BEGINNER_TO_PROFICIENT.STD.DelegatedSTD
{
    // 事件数据
    public class PriceChangedEventArgs<T> : EventArgs
    {
        public string StockSymbol { get; }

        public T NewPrice { get; }

        public PriceChangedEventArgs(string stockSymbol, T newPrice)
        {
            StockSymbol = stockSymbol;
            NewPrice = newPrice;
        }
    }

    public delegate void PriceChangedHandler<T>(object sender, PriceChangedEventArgs<T> e);

    // 发布器
    public class StockMarket<T>
    {
        private readonly Dictionary<string, T> _stockPrice = new Dictionary<string, T>();
        public event PriceChangedHandler<T> PriceChanged;

        public void AddStock(string symbol, T initialPrice) => _stockPrice[symbol] = initialPrice;

        public void RemoveStock(string symbol) => _stockPrice.Remove(symbol);

        public void UpdatePrice(string symbol, T newPrice)
        {
            if(_stockPrice.ContainsKey(symbol))
            {
                _stockPrice[symbol] = newPrice;
                OnPriceChanged(symbol, newPrice);
            }
        }

        protected virtual void OnPriceChanged(string symbol, T newPrice)
        {
            PriceChanged?.Invoke(this, new PriceChangedEventArgs<T>(symbol, newPrice));
        }
    }

    // 订阅器
    public class Investor<T>
    {
        private readonly string _name;

        public Investor(string name, StockMarket<T> market, string stockSymbol)
        {
            _name = name;
            market.PriceChanged += OnPriceChanged;
        }

        private void OnPriceChanged(Object sender, PriceChangedEventArgs<T> e)
        {
            Console.WriteLine($"{_name} notified: {e.StockSymbol} price changed {e.NewPrice}");
        }
    }

    public class DelegatedSTDP15
    {
        public static void Execute()
        {
            var market = new StockMarket<decimal>();

            market.AddStock("AAPL", 150.00m);
            market.AddStock("GOOGL", 2800.00m);

            var investor1 = new Investor<decimal>("Alice", market, "AAPL");
            var investor2 = new Investor<decimal>("Bob", market, "GOOGL");

            market.UpdatePrice("AAPL", 155.00m);
            market.UpdatePrice("GOOGL", 2900.00m);

            market.RemoveStock("AAPL");
            market.UpdatePrice("AAPL", 160.00m);
        }
    }
}
